home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 039a / dflat8.zip / HELPBOX.C < prev    next >
Text File  |  1991-09-30  |  17KB  |  655 lines

  1. /* ------------ helpbox.c ----------- */
  2.  
  3. #include "dflat.h"
  4. #include "htree.h"
  5.  
  6. extern DBOX HelpBox;
  7.  
  8. /* -------- strings of D-Flat classes for calling default
  9.       help text collections -------- */
  10. char *ClassNames[] = {
  11.     #undef ClassDef
  12.     #define ClassDef(c,b,p,a) #c,
  13.     #include "classes.h"
  14.     NULL
  15. };
  16.  
  17. #define MAXHEIGHT (SCREENHEIGHT-10)
  18.  
  19. /* --------- linked list of help text collections -------- */
  20. struct helps {
  21.     char *hname;
  22.     char *NextName;
  23.     char *PrevName;
  24.     long hptr;
  25.     int bit;
  26.     int hheight;
  27.     int hwidth;
  28.     WINDOW hwnd;
  29.     struct helps *NextHelp;
  30. };
  31. static struct helps *FirstHelp;
  32. static struct helps *LastHelp;
  33. static struct helps *ThisHelp;
  34.  
  35. /* --- linked stack of help windows that have beed used --- */
  36. struct HelpStack {
  37.     char *hname;
  38.     struct HelpStack *PrevStack;
  39. };
  40. static struct HelpStack *LastStack;
  41. static struct HelpStack *ThisStack;
  42.  
  43. /* --- linked list of keywords in the current help
  44.            text collection (listhead is in window) -------- */
  45. struct keywords {
  46.     char *hname;
  47.     int lineno;
  48.     int off1, off2, off3;
  49.     int isDefinition;
  50.     struct keywords *nextword;
  51.     struct keywords *prevword;
  52. };
  53.  
  54. static FILE *helpfp;
  55. static char hline [160];
  56. static int Helping;
  57.  
  58. static void SelectHelp(WINDOW, char *);
  59. static void ReadHelp(WINDOW);
  60. static void FindHelp(char *);
  61. static void FindHelpWindow(WINDOW);
  62. static void DisplayDefinition(WINDOW, char *);
  63. static void BestFit(WINDOW, DIALOGWINDOW *);
  64.  
  65. int HelpBoxProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  66. {
  67.     DBOX *db = wnd->extension;
  68.     WINDOW cwnd;
  69.     struct keywords *thisword;
  70.     static char HelpName[50];
  71.  
  72.     switch (msg)    {
  73.         case CREATE_WINDOW:
  74.             Helping = TRUE;
  75.             GetClass(wnd) = HELPBOX;
  76.             InitWindowColors(wnd);
  77.             if (ThisHelp != NULL)
  78.                 ThisHelp->hwnd = wnd;
  79.             break;
  80.         case INITIATE_DIALOG:
  81.             ReadHelp(wnd);
  82.             break;
  83.         case COMMAND:
  84.             if (p2 != 0)
  85.                 break;
  86.             switch ((int)p1)    {
  87.                 case ID_CANCEL:
  88.                     ThisStack = LastStack;
  89.                     while (ThisStack != NULL)    {
  90.                         LastStack = ThisStack->PrevStack;
  91.                         if (ThisStack->hname != NULL)
  92.                             free(ThisStack->hname);
  93.                         free(ThisStack);
  94.                         ThisStack = LastStack;
  95.                     }
  96.                     break;
  97.                 case ID_PREV:
  98.                     FindHelpWindow(wnd);
  99.                     if (ThisHelp != NULL)
  100.                         SelectHelp(wnd, ThisHelp->PrevName);
  101.                     return TRUE;
  102.                 case ID_NEXT:
  103.                     FindHelpWindow(wnd);
  104.                     if (ThisHelp != NULL)
  105.                         SelectHelp(wnd, ThisHelp->NextName);
  106.                     return TRUE;
  107.                 case ID_BACK:
  108.                     if (LastStack != NULL)    {
  109.                         if (LastStack->PrevStack != NULL)    {
  110.                             ThisStack = LastStack->PrevStack;
  111.                             if (LastStack->hname != NULL)
  112.                                 free(LastStack->hname);
  113.                             free(LastStack);
  114.                             LastStack = ThisStack;
  115.                             SelectHelp(wnd, ThisStack->hname);
  116.                         }
  117.                     }
  118.                     return TRUE;
  119.                 default:
  120.                     break;
  121.             }
  122.             break;
  123.         case KEYBOARD:
  124.             if (WindowMoving)
  125.                 break;
  126.             cwnd = ControlWindow(wnd->extension, ID_HELPTEXT);
  127.             if (cwnd == NULL || inFocus != cwnd)
  128.                 break;
  129.             thisword = cwnd->thisword;
  130.             switch ((int)p1)    {
  131.                 case '\r':
  132.                     if (thisword != NULL)    {
  133.                         if (thisword->isDefinition)
  134.                             DisplayDefinition(GetParent(wnd), thisword->hname);
  135.                         else    {
  136.                             strncpy(HelpName, thisword->hname,
  137.                                 sizeof HelpName);
  138.                             SelectHelp(wnd, HelpName);
  139.                         }
  140.                     }
  141.                     return TRUE;
  142.                 case '\t':
  143.                     if (thisword == NULL)
  144.                         thisword = cwnd->firstword;
  145.                     else {
  146.                         if (thisword->nextword == NULL)
  147.                             thisword = cwnd->firstword;
  148.                         else
  149.                             thisword = thisword->nextword;
  150.                     }
  151.                     break;
  152.                 case SHIFT_HT:
  153.                     if (thisword == NULL)
  154.                         thisword = cwnd->lastword;
  155.                     else {
  156.                         if (thisword->prevword == NULL)
  157.                             thisword = cwnd->lastword;
  158.                         else
  159.                             thisword = thisword->prevword;
  160.                     }
  161.                     break;
  162.                 default:
  163.                     thisword = NULL;
  164.                     break;
  165.             }
  166.             if (thisword != NULL)    {
  167.                 cwnd->thisword = thisword;
  168.                 if (thisword->lineno < cwnd->wtop ||
  169.                         thisword->lineno >= cwnd->wtop + ClientHeight(cwnd))    {
  170.                     int distance = ClientHeight(cwnd)/2;
  171.                     do    {
  172.                         cwnd->wtop = thisword->lineno - distance;
  173.                         distance /= 2;
  174.                     }
  175.                     while (cwnd->wtop < 0);
  176.                 }
  177.                 SendMessage(cwnd, PAINT, 0, 0);
  178.                 return TRUE;
  179.             }
  180.             break;
  181.         case CLOSE_WINDOW:
  182.             if (db != NULL)    {
  183.                 if (db->dwnd.title != NULL)    {
  184.                     free(db->dwnd.title);
  185.                     db->dwnd.title = NULL;
  186.                 }
  187.             }
  188.             FindHelpWindow(wnd);
  189.             if (ThisHelp != NULL)
  190.                 ThisHelp->hwnd = NULL;
  191.             Helping = FALSE;
  192.             break;
  193.         default:
  194.             break;
  195.     }
  196.     return BaseWndProc(HELPBOX, wnd, msg, p1, p2);
  197. }
  198.  
  199. static void SelectHelp(WINDOW wnd, char *hname)
  200. {
  201.     if (hname != NULL)    {
  202.         WINDOW pwnd = GetParent(wnd);
  203.         PostMessage(wnd, ENDDIALOG, 0, 0);
  204.         PostMessage(pwnd, DISPLAY_HELP, (PARAM) hname, 0);
  205.     }
  206. }
  207.  
  208. int HelpTextProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  209. {
  210.     struct keywords *thisword;
  211.     int rtn, mx, my;
  212.     switch (msg)    {
  213.         case PAINT:
  214.             if (wnd->thisword != NULL)    {
  215.                 WINDOW pwnd = GetParent(wnd);
  216.                 char *cp;
  217.                 thisword = wnd->thisword;
  218.                 cp = TextLine(wnd, thisword->lineno);
  219.                 cp += thisword->off1;
  220.                 *(cp+1) = (pwnd->WindowColors [SELECT_COLOR] [FG] & 255) | 0x80;
  221.                 *(cp+2) = (pwnd->WindowColors [SELECT_COLOR] [BG] & 255) | 0x80;
  222.                 rtn = DefaultWndProc(wnd, msg, p1, p2);
  223.                 *(cp+1) = (pwnd->WindowColors [HILITE_COLOR] [FG] & 255) | 0x80;
  224.                 *(cp+2) = (pwnd->WindowColors [HILITE_COLOR] [BG] & 255) | 0x80;
  225.                 return rtn;
  226.             }
  227.             break;
  228.         case LEFT_BUTTON:
  229.             rtn = DefaultWndProc(wnd, msg, p1, p2);
  230.             mx = (int)p1 - GetClientLeft(wnd);
  231.             my = (int)p2 - GetClientTop(wnd);
  232.             my += wnd->wtop;
  233.             thisword = wnd->firstword;
  234.             while (thisword != NULL)    {
  235.                 if (my == thisword->lineno)    {
  236.                     if (mx >= thisword->off2 && mx < thisword->off3)    {
  237.                         wnd->thisword = thisword;
  238.                         SendMessage(wnd, PAINT, 0, 0);
  239.                         if (thisword->isDefinition)    {
  240.                             WINDOW pwnd = GetParent(wnd);
  241.                             if (pwnd != NULL)
  242.                                 DisplayDefinition(GetParent(pwnd),
  243.                                     thisword->hname);
  244.                         }
  245.                         break;
  246.                     }
  247.                 }
  248.                 thisword = thisword->nextword;
  249.             }
  250.             return rtn;
  251.         case DOUBLE_CLICK:
  252.             PostMessage(wnd, KEYBOARD, '\r', 0);
  253.             break;
  254.         case CLOSE_WINDOW:
  255.             thisword = wnd->firstword;
  256.             while (thisword != NULL)    {
  257.                 struct keywords *nextword = thisword->nextword;
  258.                 if (thisword->hname != NULL)
  259.                     free(thisword->hname);
  260.                 free(thisword);
  261.                 thisword = nextword;
  262.             }
  263.             break;
  264.         default:
  265.             break;
  266.     }
  267.     return DefaultWndProc(wnd, msg, p1, p2);
  268. }
  269.  
  270. static void *fgetshelp(void)
  271. {
  272.     void *fg;
  273.     do
  274.         if ((fg = GetHelpLine(hline)) == NULL)
  275.             break;
  276.     while (*hline == ';');    /* bypassing all comments */
  277.     return fg;
  278. }
  279.  
  280. static void ReadHelp(WINDOW wnd)
  281. {
  282.     WINDOW cwnd = ControlWindow(wnd->extension, ID_HELPTEXT);
  283.     int linectr = 0;
  284.     if (cwnd == NULL)
  285.         return;
  286.     cwnd->wndproc = HelpTextProc;
  287.     /* ----- read the help text ------- */
  288.     while (TRUE)    {
  289.         unsigned char *cp = hline, *cp1;
  290.         int colorct = 0;
  291.         if (fgetshelp() == NULL)
  292.             break;
  293.         if (*hline == '<')
  294.             break;
  295.         hline[strlen(hline)-1] = '\0';
  296.         /* --- add help text to the help window --- */
  297.         while (cp != NULL)    {
  298.             if ((cp = strchr(cp, '[')) != NULL)    {
  299.                 /* ----- hit a new key word ----- */
  300.                 struct keywords *thisword;
  301.                 if (*(cp+1) != '.' && *(cp+1) != '*')    {
  302.                     cp++;
  303.                     continue;
  304.                 }
  305.                 thisword = calloc(1, sizeof(struct keywords));
  306.                 if (thisword != NULL)    {
  307.                     if (cwnd->firstword == NULL)
  308.                         cwnd->firstword = thisword;
  309.                     if (cwnd->lastword != NULL)    {
  310.                         ((struct keywords *)
  311.                             (cwnd->lastword))->nextword = thisword;
  312.                         thisword->prevword = cwnd->lastword;
  313.                     }
  314.                     cwnd->lastword = thisword;
  315.                     thisword->lineno = cwnd->wlines;
  316.                     thisword->off1 = (int) (cp - hline);
  317.                     thisword->off2 = thisword->off1 - colorct * 4;
  318.                     thisword->isDefinition = *(cp+1) == '*';
  319.                 }
  320.                 colorct++;
  321.                 *cp++ = CHANGECOLOR;
  322.                 *cp++ = (wnd->WindowColors [HILITE_COLOR] [FG] & 255) | 0x80;
  323.                 *cp++ = (wnd->WindowColors [HILITE_COLOR] [BG] & 255) | 0x80;
  324.                 cp1 = cp;
  325.                 if ((cp = strchr(cp, ']')) != NULL)    {
  326.                     if (thisword != NULL)
  327.                         thisword->off3 = thisword->off2 + (int) (cp - cp1);
  328.                     *cp++ = RESETCOLOR;
  329.                 }
  330.                 if ((cp = strchr(cp, '<')) != NULL)    {
  331.                     char *cp1 = strchr(cp, '>');
  332.                     if (cp1 != NULL)    {
  333.                         int len = (int) (cp1 - cp);
  334.                         if ((thisword->hname = calloc(1, len)) != NULL)    
  335.                             strncpy(thisword->hname, cp+1, len-1);
  336.                         memmove(cp, cp1+1, strlen(cp1));
  337.                     }
  338.                 }
  339.             }
  340.         }
  341.         PutItemText(wnd, ID_HELPTEXT, hline);
  342.         if (++linectr == ClientHeight(cwnd))
  343.             SendMessage(cwnd, PAINT, 0, 0);
  344.     }
  345. }
  346.  
  347. static int HelpLength(char *s)
  348. {
  349.     int len = strlen(s);
  350.     char *cp = strchr(s, '[');
  351.     while (cp != NULL)    {
  352.         len -= 4;
  353.         cp = strchr(cp+1, '[');
  354.     }
  355.     cp = strchr(s, '<');
  356.     while (cp != NULL)    {
  357.         char *cp1 = strchr(cp, '>');
  358.         if (cp1 != NULL)
  359.             len -= (int) (cp1-cp)+1;
  360.         cp = strchr(cp1, '<');
  361.     }
  362.     return len;
  363. }
  364.  
  365. /* ----------- load the help text file ------------ */
  366. void LoadHelpFile()
  367. {
  368.     char *cp;
  369.  
  370.     if (Helping)
  371.         return;
  372.     UnLoadHelpFile();
  373.     if ((helpfp = OpenHelpFile()) == NULL)
  374.         return;
  375.     *hline = '\0';
  376.     while (*hline != '<')    {
  377.         if (fgetshelp() == NULL)    {
  378.             fclose(helpfp);
  379.                return;
  380.         }
  381.     }
  382.     while (*hline == '<')   {
  383.         if (strncmp(hline, "<end>", 5) == 0)
  384.             break;
  385.  
  386.         if ((ThisHelp = calloc(1, sizeof(struct helps))) == NULL)
  387.             break;
  388.  
  389.         if (FirstHelp == NULL)
  390.             FirstHelp = ThisHelp;
  391.  
  392.         /* -------- parse the help window's text name ----- */
  393.         if ((cp = strchr(hline, '>')) == NULL)
  394.             continue;
  395.         *cp = '\0';
  396.         if ((ThisHelp->hname=malloc(strlen(hline+1)+1))==NULL)
  397.             break;
  398.         strcpy(ThisHelp->hname, hline+1);
  399.  
  400.         HelpFilePosition(&ThisHelp->hptr, &ThisHelp->bit);
  401.  
  402.         if (fgetshelp() == NULL)
  403.             break;
  404.  
  405.         /* ------- build the help linked list entry --- */
  406.         while (*hline == '[')    {
  407.             HelpFilePosition(&ThisHelp->hptr, &ThisHelp->bit);
  408.             /* ------ parse the <<prev button pointer ------- */
  409.             if (strncmp(hline, "[<<]", 4) == 0)    {
  410.                 char *cp = strchr(hline+4, '<');
  411.                 if (cp != NULL)    {
  412.                     char *cp1 = strchr(cp, '>');
  413.                     if (cp1 != NULL)    {
  414.                         int len = (int) (cp1-cp);
  415.                         ThisHelp->PrevName = calloc(1, len);
  416.                         if (ThisHelp->PrevName != NULL)
  417.                             strncpy(ThisHelp->PrevName, cp+1, len-1);
  418.                     }
  419.                 }
  420.                 if (fgetshelp() == NULL)
  421.                     break;
  422.                 continue;
  423.             }
  424.             /* ------ parse the next>> button pointer ------- */
  425.             else if (strncmp(hline, "[>>]", 4) == 0)    {
  426.                 char *cp = strchr(hline+4, '<');
  427.                 if (cp != NULL)    {
  428.                     char *cp1 = strchr(cp, '>');
  429.                     if (cp1 != NULL)    {
  430.                         int len = (int) (cp1-cp);
  431.                         ThisHelp->NextName = calloc(1, len);
  432.                         if (ThisHelp->NextName != NULL)
  433.                             strncpy(ThisHelp->NextName, cp+1, len-1);
  434.                     }
  435.                 }
  436.                 if (fgetshelp() == NULL)
  437.                     break;
  438.                 continue;
  439.             }
  440.             else
  441.                 break;
  442.         }
  443.         ThisHelp->hheight = 0;
  444.         ThisHelp->hwidth = 0;
  445.         ThisHelp->NextHelp = NULL;
  446.  
  447.         /* ------ append entry to the linked list ------ */
  448.         if (LastHelp != NULL)
  449.             LastHelp->NextHelp = ThisHelp;
  450.         LastHelp = ThisHelp;
  451.  
  452.         /* -------- move to the next <> token ------ */
  453.         if (fgetshelp() == NULL)
  454.             strcpy(hline, "<end>");
  455.         while (*hline != '<')    {
  456.             ThisHelp->hwidth =
  457.                 max(ThisHelp->hwidth, HelpLength(hline));
  458.             ThisHelp->hheight++;
  459.             if (fgetshelp() == NULL)
  460.                 strcpy(hline, "<end>");
  461.         }
  462.     }
  463.     fclose(helpfp);
  464. }
  465.  
  466. /* ------ free the memory used by the help file table ------ */
  467. void UnLoadHelpFile(void)
  468. {
  469.     while (FirstHelp != NULL)    {
  470.         ThisHelp = FirstHelp;
  471.         if (ThisHelp->hname != NULL)
  472.             free(ThisHelp->hname);
  473.         if (ThisHelp->PrevName != NULL)
  474.             free(ThisHelp->PrevName);
  475.         if (ThisHelp->NextName != NULL)
  476.             free(ThisHelp->NextName);
  477.         FirstHelp = ThisHelp->NextHelp;
  478.         free(ThisHelp);
  479.     }
  480.     ThisHelp = LastHelp = NULL;
  481. }
  482.  
  483. /* ------------ display help text ----------- */
  484. int DisplayHelp(WINDOW wnd, char *Help)
  485. {
  486.     if (Helping)
  487.         return TRUE;
  488.     FindHelp(Help);
  489.     if (ThisHelp != NULL)    {
  490.         if (LastStack == NULL || stricmp(Help, LastStack->hname))    {
  491.             ThisStack = calloc(1,sizeof(struct HelpStack));
  492.             if (ThisStack != NULL)    {
  493.                 ThisStack->hname = malloc(strlen(Help)+1);
  494.                 if (ThisStack->hname != NULL)
  495.                     strcpy(ThisStack->hname, Help);
  496.                 ThisStack->PrevStack = LastStack;
  497.                 LastStack = ThisStack;
  498.             }
  499.         }
  500.         if ((helpfp = OpenHelpFile()) != NULL)    {
  501.             DBOX *db;
  502.             int offset, i;
  503.  
  504.             if ((db = calloc(1,sizeof HelpBox)) != NULL)    {
  505.                 memcpy(db, &HelpBox, sizeof HelpBox);
  506.                 SeekHelpLine(ThisHelp->hptr, ThisHelp->bit);
  507.                    fgetshelp();
  508.                 hline[strlen(hline)-1] = '\0';
  509.                 if ((db->dwnd.title = malloc(strlen(hline)+1)) != NULL)
  510.                     strcpy(db->dwnd.title, hline);
  511.                 db->dwnd.h = min(ThisHelp->hheight, MAXHEIGHT)+7;
  512.                 db->dwnd.w = max(45, ThisHelp->hwidth+6);
  513.                 BestFit(wnd, &db->dwnd);
  514.                 db->ctl[0].dwnd.w = max(40, ThisHelp->hwidth+2);
  515.                 db->ctl[0].dwnd.h = min(ThisHelp->hheight, MAXHEIGHT)+2;
  516.                 offset = (db->dwnd.w-40) / 2;
  517.                 for (i = 1; i < 5; i++)    {
  518.                     db->ctl[i].dwnd.y = min(ThisHelp->hheight, MAXHEIGHT)+3;
  519.                     db->ctl[i].dwnd.x += offset;
  520.                 }
  521.                 if (ThisStack != NULL)
  522.                     if (ThisStack->PrevStack == NULL)
  523.                         DisableButton(db, ID_BACK);
  524.                 if (ThisHelp->NextName == NULL)
  525.                     DisableButton(db, ID_NEXT);
  526.                 if (ThisHelp->PrevName == NULL)
  527.                     DisableButton(db, ID_PREV);
  528.                 DialogBox(wnd, db, TRUE, HelpBoxProc);
  529.             }
  530.             fclose(helpfp);
  531.             return TRUE;
  532.         }
  533.     }
  534.     return FALSE;
  535. }
  536.  
  537. static void DisplayDefinition(WINDOW wnd, char *def)
  538. {
  539.     WINDOW dwnd;
  540.     WINDOW hwnd = wnd;
  541.     int y;
  542.  
  543.     if (GetClass(wnd) == POPDOWNMENU)
  544.         hwnd = GetParent(wnd);
  545.     y = GetClass(hwnd) == MENUBAR ? 2 : 1;
  546.     FindHelp(def);
  547.     if (ThisHelp != NULL)    {
  548.         clearBIOSbuffer();
  549.         if ((helpfp = OpenHelpFile()) != NULL)    {
  550.             clearBIOSbuffer();
  551.             dwnd = CreateWindow(TEXTBOX,
  552.                                NULL,
  553.                                GetClientLeft(hwnd),
  554.                                GetClientTop(hwnd)+y,
  555.                                min(ThisHelp->hheight, MAXHEIGHT)+3,
  556.                                ThisHelp->hwidth+2,
  557.                                NULL,
  558.                                wnd,
  559.                                NULL,
  560.                                HASBORDER | NOCLIP | SAVESELF);
  561.             if (dwnd != NULL)    {
  562.                 clearBIOSbuffer();
  563.                 /* ----- read the help text ------- */
  564.                 SeekHelpLine(ThisHelp->hptr, ThisHelp->bit);
  565.                 while (TRUE)    {
  566.                     clearBIOSbuffer();
  567.                     if (fgetshelp() == NULL)
  568.                         break;
  569.                     if (*hline == '<')
  570.                         break;
  571.                     hline[strlen(hline)-1] = '\0';
  572.                     SendMessage(dwnd, ADDTEXT, (PARAM) hline, 0);
  573.                 }
  574.                 SendMessage(dwnd, SHOW_WINDOW, 0, 0);
  575.                 SendMessage(NULL, WAITKEYBOARD, 0, 0);
  576.                 SendMessage(NULL, WAITMOUSE, 0, 0);
  577.                 SendMessage(dwnd, CLOSE_WINDOW, 0, 0);
  578.             }
  579.             fclose(helpfp);
  580.         }
  581.     }
  582. }
  583.  
  584. static int wildcmp(char *s1, char *s2)
  585. {
  586.     while (*s1 || *s2)    {
  587.         if (tolower(*s1) != tolower(*s2))
  588.             if (*s1 != '?' && *s2 != '?')
  589.                 return 1;
  590.         s1++, s2++;
  591.     }
  592.     return 0;
  593. }
  594.  
  595. static void FindHelp(char *Help)
  596. {
  597.     ThisHelp = FirstHelp;
  598.     while (ThisHelp != NULL)    {
  599.         if (wildcmp(Help, ThisHelp->hname) == 0)
  600.             break;
  601.         ThisHelp = ThisHelp->NextHelp;
  602.     }
  603. }
  604.  
  605. static void FindHelpWindow(WINDOW wnd)
  606. {
  607.     ThisHelp = FirstHelp;
  608.     while (ThisHelp != NULL)    {
  609.         if (wnd == ThisHelp->hwnd)
  610.             break;
  611.         ThisHelp = ThisHelp->NextHelp;
  612.     }
  613. }
  614.  
  615. static int OverLap(int a, int b)
  616. {
  617.     int ov = a - b;
  618.     if (ov < 0)
  619.         ov = 0;
  620.     return ov;
  621. }
  622.  
  623. /* ------ compute the best location for a dialog box ----- */
  624. static void BestFit(WINDOW wnd, DIALOGWINDOW *dwnd)
  625. {
  626.     int above, below, right, left;
  627.     if (GetClass(wnd) == MENUBAR || GetClass(wnd) == APPLICATION)    {
  628.         dwnd->x = dwnd->y = -1;
  629.         return;
  630.     }
  631.     /* --- compute above overlap ---- */
  632.     above = OverLap(dwnd->h, GetTop(wnd));
  633.     /* --- compute below overlap ---- */
  634.     below = OverLap(GetBottom(wnd), SCREENHEIGHT-dwnd->h);
  635.     /* --- compute right overlap ---- */
  636.     right = OverLap(GetRight(wnd), SCREENWIDTH-dwnd->w);
  637.     /* --- compute left  overlap ---- */
  638.     left = OverLap(dwnd->w, GetLeft(wnd));
  639.  
  640.     if (above < below)
  641.         dwnd->y = max(0, GetTop(wnd)-dwnd->h-2);
  642.     else
  643.         dwnd->y = min(SCREENHEIGHT-dwnd->h, GetBottom(wnd)+2);
  644.     if (right < left)
  645.         dwnd->x = min(GetRight(wnd)+2, SCREENWIDTH-dwnd->w);
  646.     else
  647.         dwnd->x = max(0, GetLeft(wnd)-dwnd->w-2);
  648.  
  649.     if (dwnd->x == GetRight(wnd)+2 || dwnd->x == GetLeft(wnd)-dwnd->w-2)
  650.         dwnd->y = -1;
  651.     if (dwnd->y ==GetTop(wnd)-dwnd->h-2 || dwnd->y == GetBottom(wnd)+2)
  652.         dwnd->x = -1;
  653. }
  654.  
  655.